package com.ybear.ybmediax.media;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioAttributes;
import android.media.MediaDataSource;
import android.media.MediaPlayer;
import android.media.PlaybackParams;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ybear.ybutils.utils.log.LogUtil;
import com.ybear.ybutils.utils.handler.Handler;
import com.ybear.ybutils.utils.handler.HandlerManage;

import java.io.FileDescriptor;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class MediaX implements MediaXCallback, MediaPlayer.OnCompletionListener,
        MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnErrorListener {

    public interface CallVideoInfo {
        void onSource(@NonNull Data data);
        void onInfo(int progress, int total);
        void onProgress(int progress);
    }

    private final List<Data> mDataList = new ArrayList<>();
    private final Context mContext;
    private final AtomicInteger mAtoPrepared = new AtomicInteger( 0 );

    @Nullable
    private MediaPlayer mMediaPlayer;
//    private Timer mTimerProgress;
    private MediaXStatus mStatus;
    private Handler mHandler;
    private int mPlayIndex;
    private int mCurrentProgress;
    private int mVideoWidth, mVideoHeight;
//    private int oldAngle;
//    private int mWidth, mHeight;
//    private boolean isEnableOrientation = true;
    private Data mCurrentData;
//    private int mPrepared = 0;
    private boolean isLooping;
    private boolean isPlaying;
    private boolean isResume;

    private Thread mPlayThread;
    private Thread mPauseThread;
    private Thread mStopThread;
    private Thread mPreparedThread;

    private long mPlayOutTimeMillis;
    private long mPauseOutTimeMillis;
    private long mStopOutTimeMillis;

//    private ScreenOrientationEventListener mScreenOrientationEventListener;
//    private ScreenOrientationChangeListener mOrientationChanged;
    private CallVideoInfo mCallVideoInfo;

    public MediaX(Context context) {
        mContext = context;
        init();
        initMediaPlayer();
    }

//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        if( mWidth == 0 || mHeight == 0 ) {
//            mWidth = getMeasuredWidth();
//            mHeight = getMeasuredHeight();
//            //启动屏幕旋转监听
//            if( isEnableOrientation ) mScreenOrientationEventListener.enable();
//        }
//    }

    private void init() {
        mHandler = HandlerManage.create();
        initValue();
//        if( mScreenOrientationEventListener == null ) {
//            mScreenOrientationEventListener = new ScreenOrientationEventListener( mContext );
//            mScreenOrientationEventListener.setScreenOrientationChangeListener( this );
//        }
//        getHolder().addCallback( this );
//        /* viewpager等控件滑动时不会出现白屏现象 */
//        getHolder().setFormat( PixelFormat.TRANSPARENT );
//        //显示在最顶层
//        setZOrderOnTop( true );
//        /* 允许被点击 */
//        setFocusable( true );
//        setClickable( true );
    }

    private void initValue() {
        mStatus = null;
        mDataList.clear();
        //默认播放第一条
        mPlayIndex = 0;
        mCurrentProgress = 0;
        mVideoWidth = -1;
        mVideoHeight = -1;
//        oldAngle = 90;
//        mWidth = 0;
//        mHeight = 0;
        isLooping = false;
        isPlaying = false;
        isResume = false;
//        isEnableOrientation = true;
//        mPrepared = 0;
        initPrepared( 1 );
        mPlayThread = null;
        mPauseThread = null;
    }

//    @Override
//    public void setEnableOrientation(boolean enable) {
//        isEnableOrientation = enable;
//    }

    private boolean checkData(Data data) {
        return data != null && ( mCurrentData == null || !mCurrentData.isEq( data ) );
    }

    /**
     * 设置资源
     * @param data   资源
     */
    private void setSource(Data data) throws IOException {
        if( mMediaPlayer == null || !checkData( data ) ) return;
        LogUtil.e("MediaX -> setSource:" + data.getData() );
        reset();
        mCurrentData = data;
//        mPrepared = 0;
        initPrepared( 1 );
        Object obj = data.getData();
        if( obj instanceof String ) {
            mMediaPlayer.setDataSource( obj.toString() );
        }else if( obj instanceof Uri ) {
            Uri uri = (Uri) obj;
            //Uri
            Map<String, String> headers = data.getHeaders();
            List<HttpCookie> cookies = data.getCookies();
            if( headers != null ) {
                if( cookies != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) {
                    //uri, headers, cookies
                    mMediaPlayer.setDataSource( mContext, uri, headers, cookies );
                }else {
                    //uri, headers
                    mMediaPlayer.setDataSource( mContext, uri, headers );
                }
            }else {
                //uri
                mMediaPlayer.setDataSource( mContext, uri );
            }
        }else if( obj instanceof FileDescriptor ) {
            //FileDescriptor
            long offset = data.getOffset();
            long len = data.getLength();
            try {
                if( offset != -1 && len != -1 ) {
                    //fd, offset, length
                    mMediaPlayer.setDataSource( (FileDescriptor)obj, offset, len );
                }else {
                    //fd
                    mMediaPlayer.setDataSource( (FileDescriptor)obj );
                }
            } catch (IOException | IllegalArgumentException | IllegalStateException e) {
                e.printStackTrace();
            }
        }else if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) {
            //AssetFileDescriptor
            if ( obj instanceof AssetFileDescriptor ) {
                mMediaPlayer.setDataSource( (AssetFileDescriptor) obj );
            }
        }else if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
            //MediaDataSource
            if( obj instanceof MediaDataSource ) {
                mMediaPlayer.setDataSource( (MediaDataSource) obj );
            }
        }
        //是否循环播放
        mMediaPlayer.setLooping( isLooping );

        try {
            mMediaPlayer.prepareAsync();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        if( mCallVideoInfo != null ) mCallVideoInfo.onSource( data );
    }

    void setObjData(@NonNull Data obj) {
        if( mMediaPlayer != null ) {
            try {
                setSource( obj );
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    MediaX setDataSource(boolean isAddObjData, String... paths) {
        if( paths == null || paths.length <= 0 ) return this;
        for (String path : paths) {
            if( TextUtils.isEmpty( path ) ) continue;
            for( Data data : mDataList ) {
                if( data == null || path.equals( data.getData() ) ) {
                    mDataList.add( new Data( path ) );
                }
            }
        }
        if( isAddObjData ) setObjData( new Data( paths[ 0 ] ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param paths 资源
     */
    @Override
    public MediaX setDataSource(String... paths) {
        return setDataSource( true, paths );
    }

    /**
     * 设置视频资源
     * @param uris  资源
     */
    @Override
    public MediaX setDataSource(Uri... uris) {
        if( uris == null || uris.length <= 0 ) return this;

        for (Uri path : uris) mDataList.add( new Data( path ) );
        setObjData( new Data( uris[ 0 ] ) );

//        for ( Uri uri : uris ) setObjData( new Data( uri ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param uri       资源
     * @param headers   Header
     */
    @Override
    public MediaX setDataSource(@NonNull Uri uri, @Nullable Map<String, String> headers) {
        setObjData( new Data( uri, headers ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param uri       资源
     * @param headers   Header
     * @param cookies   Cookie
     */
    @Override
    public MediaX setDataSource(@NonNull Uri uri,
                                                          @Nullable Map<String, String> headers,
                                                          @Nullable List<HttpCookie> cookies) {
        setObjData( new Data( uri, headers, cookies ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param fds  资源
     */
    @Override
    public MediaX setDataSource(FileDescriptor... fds) {
        if( fds == null || fds.length <= 0 ) return this;

        for (FileDescriptor fd : fds) mDataList.add( new Data( fd ) );
        setObjData( new Data( fds[ 0 ] ) );

//        for ( FileDescriptor fd : fds ) setObjData( new Data( fd ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param fd        资源
     * @param offset    资源开始位置
     * @param length    长度
     */
    public MediaX setDataSource(@NonNull FileDescriptor fd, long offset, long length) {
        setObjData( new Data( fd, offset, length ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param fds  资源
     */
    @Override
    public MediaX setDataSource(AssetFileDescriptor... fds) {
        if( fds == null || fds.length <= 0 ) return this;

        for (AssetFileDescriptor fd : fds) mDataList.add( new Data( fd ) );
        setObjData( new Data( fds[ 0 ] ) );

//        for ( AssetFileDescriptor fd : fds ) setObjData( new Data( fd ) );
        return this;
    }

    /**
     * 设置视频资源
     * @param dss  资源
     */
    @Override
    public MediaX setDataSource(MediaDataSource... dss) {
        if( dss == null || dss.length <= 0 ) return this;

        for (MediaDataSource ds : dss) mDataList.add( new Data( ds ) );
        setObjData( new Data( dss[ 0 ] ) );

//        for ( MediaDataSource ds : dss ) setObjData( new Data( ds ) );
        return this;
    }

    public Data getCurrentData() { return mCurrentData; }

    /**
     * 播放视频
     */
    @Override
    public void play() {
        LogUtil.e("MediaX -> Play -> " +
                "isPrepared:" + getPreparedStatus() + " | " +
                "isPlaying:" + isPlaying()
        );
//        if( isPlaying() ) {
//            mHandler.post(this::stopSync);
//            mHandler.postDelayed( this::play, 200 );
//            return;
//        }
        if( getPreparedStatus() == 1 ) {
            mHandler.post(this::playSync);
            return;
        }
        if( mPlayThread != null ) return;
        mPlayThread = new Thread(() -> {
            mPlayOutTimeMillis = System.currentTimeMillis();
            //自旋等待
            while ( true ) {
                if( getPreparedStatus() == -1 ) {
                    LogUtil.e("MediaX -> Play error:" + mAtoPrepared.get() );
                    break;
                }
                if( getPreparedStatus() == 0 ) {
                    waitThread( mPlayThread );
                    continue;
                }
//                seekTo( mCurrentProgress );
                play();
                break;
            }
            mPlayThread = null;
            mPlayOutTimeMillis = 0;
        });
        mPlayThread.start();
    }

    private void playSync() {
        if( mMediaPlayer == null ) return;
        try {
            //播放速度
            refreshSpeed();
            //播放
            mMediaPlayer.start();
            isPlaying = true;
            updateCurrentPosition();
            //回调视频信息
            if( mCallVideoInfo != null ) {
                mCallVideoInfo.onInfo( mMediaPlayer.getCurrentPosition(), mMediaPlayer.getDuration() );
            }
            if( mStatus != null ) mStatus.onPlay();
        } catch (IllegalStateException e) {
            e.printStackTrace();
            isPlaying = false;
            callCompletion( false );
        }
    }

    @Override
    public void play(long delayed) {
        if( delayed <= 0 ) {
            play();
        }else {
            mHandler.post(this::play, delayed);
        }
    }

    /**
     * 暂停视频
     */
    @Override
    public void pause() {
        LogUtil.e("MediaX -> Pause -> " +
                "isPrepared:" + getPreparedStatus() + " | " +
                "isPlaying:" + isPlaying()
        );
        if( isPlaying() ) {
            mHandler.post(this::pauseSync);
            return;
        }
        if( mPauseThread != null ) return;
        mPauseThread = new Thread(() -> {
            mPauseOutTimeMillis = System.currentTimeMillis();
            //自旋等待
            while ( true ) {
                if( getPreparedStatus() == -1 ) {
                    LogUtil.e("MediaX -> Pause error:" + mAtoPrepared.get() );
                    break;
                }
                if( getPreparedStatus() == 0 || !isPlaying() ) {
                    waitThread( mPauseThread );
                    continue;
                }
                pause();
                break;
            }
            mPauseThread = null;
            mPauseOutTimeMillis = 0;
        });
        mPauseThread.start();
    }

    private void pauseSync() {
        if( mMediaPlayer == null ) return;
        try {
            mMediaPlayer.pause();
            isPlaying = false;
            if( mStatus != null ) mStatus.onPause();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止播放
     */
    @Override
    public void stop() {
        LogUtil.e("MediaX -> Stop -> " +
                "isPrepared:" + getPreparedStatus() + " | " +
                "isPlaying:" + isPlaying()
        );
        if( isPlaying() ) {
            mHandler.post(this::stopSync);
            return;
        }
        if( mStopThread != null ) return;
        mStopThread = new Thread(() -> {
            mStopOutTimeMillis = System.currentTimeMillis();
            //自旋等待
            while ( true ) {
                if( getPreparedStatus() == -1 ) {
                    LogUtil.e("MediaX -> Stop error:" + mAtoPrepared.get() );
                    break;
                }
                if( getPreparedStatus() == 0 || !isPlaying() ) {
                    waitThread( mStopThread );
                    continue;
                }
                stop();
                break;
            }
            mStopThread = null;
            mStopOutTimeMillis = 0;
        });
        mStopThread.start();
    }

    private void stopSync() {
        if( mMediaPlayer == null ) return;
        try {
            mMediaPlayer.stop();
            mMediaPlayer.seekTo( 0 );
            initPrepared();
            isPlaying = false;
            if( mStatus != null ) mStatus.onStop();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上一个视频
     */
    @Override
    public void on() {
        if( mPlayIndex > 0 ) select( --mPlayIndex );
    }

    /**
     * 下一个视频
     */
    @Override
    public void next() {
        if( mPlayIndex + 1 < mDataList.size() ) select( ++mPlayIndex );
    }

    @Override
    public void select(int index) {
        if( index < 0 || index >= mDataList.size() ) return;
        try {
            setSource( mDataList.get( index ) );
        } catch (IOException e) {
            e.printStackTrace();
        }
        play();
    }

    /**
     * 恢复播放。当调用过 {@link #resumePause()} 时，会恢复之前的播放状态。
     * 例如：上次是用户发起暂停，恢复时也会暂停。当Activity发起暂停，恢复时播放。
     * 但一般情况下用不上，因为播放器会在暂停和恢复时自动调用。
     */
    public void resumePlay() {
        if( !isResume ) return;
        isResume = false;
        play();
    }

    /**
     * 配合{@link #resumePlay()}一起使用。
     */
    public void resumePause() {
        if( isPlaying() ) isResume = true;
        pause();
    }

    /**
     * 重置
     */
    @Override
    public void reset() {
        if( mMediaPlayer == null ) return;
        try {
            mMediaPlayer.reset();
//            mPrepared = 0;
            initPrepared();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if( mStatus != null ) mStatus.onReset();
//        initValue();
    }

    /**
     * 释放资源
     */
    @Override
    public void release() {
        stop();
//        if( mTimerProgress != null ) {
//            mTimerProgress.cancel();
//            mTimerProgress = null;
//        }
//        if( mScreenOrientationEventListener != null ) {
//            mScreenOrientationEventListener.disable();
//            mTimerProgress = null;
//        }
        if( mMediaPlayer != null ) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }

//        Canvas canvas = getHolder().lockCanvas();
//        if( canvas != null ) {
//            canvas.drawColor( Color.BLACK );
//            getHolder().unlockCanvasAndPost( canvas );
//        }
        if( mStatus != null ) mStatus.onRelease();
        initValue();
    }

    private float mSpeed = 1.0F;
    public MediaX setSpeed(float speed) {
        mSpeed = speed;
        refreshSpeed();
        return this;
    }

    public float getSpeed() { return mSpeed; }

    /**
     * 滑动视频进度到指定位置
     * @param progress  进度
     */
    @Override
    public MediaX seekTo(int progress) {
        if( mMediaPlayer == null ) return this;
        mCurrentProgress = progress;
        if( getPreparedStatus() != 1 ) return this;
        try {
            mMediaPlayer.seekTo( progress );
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * 是否循环播放视频，多个视频时从第一个视频开始循环
     * @param enable    是否启用
     */
    @Override
    public MediaX setLooping(boolean enable) {
        isLooping = enable;
        return this;
    }

    /**
     * 是否在循环播放
     * @return  结果
     */
    @Override
    public boolean isLooping() {
        if( mMediaPlayer == null ) return false;
        return mMediaPlayer.isLooping();
    }

    /**
     * 是否在播放
     * @return  结果
     */
    @Override
    public boolean isPlaying() { return getPreparedStatus() == 1 && isPlaying; }

    /**
     * 视频状态监听器
     * @param l     监听器
     */
    @Override
    public MediaX setOnMediaStatusListener(MediaXStatus l) {
        mStatus = l;
        return this;
    }

//    /**
//     * 跟随系统旋转
//     * @param enable    是否启用
//     */
//    @Override
//    public void setFollowSystemRotation(boolean enable) {
//        mScreenOrientationEventListener.setFollowSystemRotation( enable );
//    }
//
//    /**
//     * 设置屏幕方向改变监听
//     * @param l     监听器
//     */
//    @Override
//    public void setOrientationChangedListener(ScreenOrientationChangeListener l) {
//        mOrientationChanged = l;
//    }

//    /**
//     * 设置屏幕方向
//     * @param orientation   方向
//     * @param angle         角度
//     */
//    public void setOrientationChange(int orientation, int angle) {
//        changeOrientation( orientation, angle );
//    }

    /**
     * 视频信息监听器
     * @param call  回调
     */
    public void setVideoInfoListener(CallVideoInfo call) { this.mCallVideoInfo = call; }

    /**
     * 设置音量大小
     * @param lVolume   左声道
     * @param rVolume   右声道
     */
    public void setVolume(float lVolume, float rVolume) {
        if( mMediaPlayer != null ) mMediaPlayer.setVolume( lVolume, rVolume );
    }

    /**
     * 设置音量大小
     * @param volume    音量大小
     */
    public void setVolume(float volume) { setVolume( volume, volume ); }

    /**
     * 当前视频播放进度
     * @return  进度
     */
    public int getCurrentProgress() { return mCurrentProgress; }

    public int getWidth() { return mVideoWidth; }

    public int getVideoHeight() { return mVideoHeight; }

    void initMediaPlayer() {
//        //屏幕保持常亮
//        setKeepScreenOn( true );
        //防止当前方法重复调用
        if( mMediaPlayer != null ) return;
        try {
            mMediaPlayer = new MediaPlayer();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mMediaPlayer.setAudioAttributes( new AudioAttributes.Builder().build() );
            }
            //设置资源
            if( mCurrentData != null ) setSource( new Data( mCurrentData ) );

        } catch (Exception e) {
            e.printStackTrace();
            if( mStatus != null ) mStatus.onError( -1, -1 );
        }
        //错误监听器
        mMediaPlayer.setOnErrorListener( this );
        //添加完成监听器
        mMediaPlayer.setOnCompletionListener( this );
        //流媒体缓冲进度
        mMediaPlayer.setOnBufferingUpdateListener( this );
        //准备就绪时回调
        mMediaPlayer.setOnPreparedListener(mp -> {
//            mPrepared++;
            mAtoPrepared.incrementAndGet();
            //自旋等待
            preparedSpinWait();
        });


//        if( mTimerProgress == null ) {
//            //进度计时器
//            mTimerProgress = new Timer();
//            mTimerProgress.schedule(new TimerTask() {
//                @Override
//                public void run() {
//                    if( mCallVideoInfo == null || !isPlaying() ) return;
//                    mHandler.post(() -> {
//                        try {
//                            mCurrentProgress = mMediaPlayer.getCurrentPosition();
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                        } finally {
//                            //回调视频信息
//                            mCallVideoInfo.onProgress( mCurrentProgress );
//                        }
//                    });
//
//                }
//            }, 0, 1500);
//        }
    }
//
    private void updateCurrentPosition() {
        mHandler.post(() -> {
            if( !isPlaying ) return;
            if( mMediaPlayer == null || mCallVideoInfo == null || !isPlaying() ) {
                updateCurrentPosition();
                return;
            }
            try {
                mCurrentProgress = mMediaPlayer.getCurrentPosition();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //回调视频信息
                mCallVideoInfo.onProgress( mCurrentProgress );
                updateCurrentPosition();
            }
        }, 1000);
    }

    /**
     * mPrepared > 1 时播放和暂停的自旋等待才会停止，而此回调接口有时候只返回一次，这边补齐。
     */
    private void preparedSpinWait() {
        LogUtil.d( "MediaX -> preparedSpinWait -> mPrepared: " + mAtoPrepared.get() );
        if( mPreparedThread != null ) return;
        mPreparedThread = new Thread(() -> {
            long curTime = System.nanoTime();
            do {
                if( System.nanoTime() - curTime >= 2000 ) {
//                    mPrepared++;
                    mAtoPrepared.incrementAndGet();
                }
            }while( mAtoPrepared.get() < 2 );
            LogUtil.d("MediaX -> preparedSpinWait -> Thread -> mPrepared: " + mAtoPrepared.get() + " | " +
                    "isPlaying: " + isPlaying + " | " +
                    "data: " + mCurrentData
            );
            if( mMediaPlayer != null ) mMediaPlayer.seekTo( 0 );
            mPreparedThread = null;
        });
        mPreparedThread.start();
    }

    /**
     初始化Prepared
     @param code    -1：抛异常时，0：默认（仅初始化完毕时才有效），1：强制初始化
     */
    private void initPrepared(int code) {
        if( code == 0 && mAtoPrepared.get() >= 2 ) return;
        mAtoPrepared.set( code );
    }

    private void initPrepared() { initPrepared( 0 ); }

    private void waitThread(Thread thread) {
        if( thread == null ) return;
        try {
            thread.join( 200 );
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     准备状态
     @return        -1：加载失败，1：加载成功，0：等待加载
     */
    private int getPreparedStatus() {
        int i = mAtoPrepared.get();
        return i == -1 ? -1 : i > 1 ? 1 : 0;
    }

//    /**
//     * 屏幕旋转发生改变
//     * @param orientation   方向
//     * @param angle         角度
//     */
//    @Override
//    public void onOrientationChange(int orientation, int angle) {
//        mPool.execute(() -> {
//            changeOrientation( orientation, angle );
//            try {
//                Thread.sleep( 1500 );
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        });
//    }

//    /**
//     * 改变旋转方向
//     * @param orientation   方向
//     * @param angle         角度
//     */
//    private void changeOrientation(int orientation, int angle) {
//        if( mWidth == 0 || mHeight == 0 ) return;
//        mHandler.post(() -> {
//            if( mOrientationChanged != null ) {
//                mOrientationChanged.onOrientationChange( orientation, angle );
//            }
//            updateOrientation( angle );
//        });
//        LogUtil.d("changeOrientation: " + orientation + " | " + angle);
//    }



//    /**
//     * 旋转更新
//     * 屏幕旋转需要考虑旋转后的高宽变化，例如：竖屏时，高比宽大，横屏时：高比宽小。
//     * 所以旋转后要确定那边为宽，那边为高，然后将视频等比例缩放至屏幕相应大小。
//     * @param angle     旋转角度 0和180 -> 横屏，90和270 -> 竖屏
//     */
//    private void updateOrientation(int angle) {
//        if( mMediaPlayer == null || mVideoWidth <= 0 || mVideoHeight <= 0 ) return;
//        ViewGroup.LayoutParams lp = getLayoutParams();
//        //是否为横版视频
//        boolean isLandscapeVideo = mVideoWidth > mVideoHeight;
//        //是否为横屏
//        boolean isLandscapeScreen = angle == 0 || angle == 180;
//        if( !isLandscapeScreen ) isLandscapeScreen = mWidth > mHeight;
//        /* 因为横竖屏原因，高宽会发生改变，所以需要取最值来判断高宽 */
//        int max = mWidth < mHeight ? mHeight : mWidth;
//        int min = mWidth > mHeight ? mHeight : mWidth;
//
//        //-1为平放状态
//        if( angle == -1 ) angle = oldAngle;
//
//        /* 屏幕旋转一共四种结果：竖屏横视频、竖屏竖视频、横屏横视频、横屏竖视频
//         * 其次，这是经过一段很长的代码精简而来，请不要尝试去理解这些代码。
//         * 大概意思是横竖屏时判断当前视频的横竖，对高宽进行等比缩放 */
//        if( (isLandscapeVideo && isLandscapeScreen) || (!isLandscapeVideo && !isLandscapeScreen) ) {
//            /* 横屏 横视频 和 竖屏 竖视频 */
//            lp.width = Utils.calcAspectRatio(
//                    mVideoWidth, mVideoHeight, isLandscapeScreen ? min : max, false
//            );
//            if( lp.width > ( isLandscapeScreen ? max : min ) ) {
//                lp.height = Utils.calcAspectRatio(
//                        mVideoWidth,
//                        mVideoHeight,
//                        isLandscapeScreen ? max : min,
//                        true
//                );
//                lp.width = isLandscapeScreen ? max : min;
//            }else {
//                lp.height = isLandscapeScreen ? min : max;
//            }
//        }else {
//            /* 竖屏 横视频 和 横屏 竖视频 */
//            int w = mVideoHeight;
//            int h = mVideoWidth;
//            lp.width = min + Utils.calcAspectRatio( w, h, min, isLandscapeScreen );
//            lp.height = isLandscapeScreen ? min : lp.width - min;
//            lp.width = isLandscapeScreen ? lp.width - min : min;
//        }
//        setLayoutParams( lp );
//        if( angle != -1 ) oldAngle = angle;
//    }

    /**
     改变播放速度
     */
    private void refreshSpeed() {
        try {
            if( mMediaPlayer == null ) return;
            int playingStatus = isPlaying ? 1 : 0;
            if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
                //获取播放参数
                PlaybackParams params = mMediaPlayer.getPlaybackParams();
                if( params == null ) params = new PlaybackParams();
                if( params.getSpeed() == mSpeed ) return;
                //暂停播放
                if( playingStatus == 1 ) {
                    mMediaPlayer.pause();
                    playingStatus = 2;
                }
                //修改播放速度
                mMediaPlayer.setPlaybackParams( params.setSpeed( mSpeed ) );
                //继续播放
                if( playingStatus == 2 ) mMediaPlayer.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 视频播放完成
     * @param mp    播放器
     */
    @Override
    public void onCompletion(MediaPlayer mp) {
        isPlaying = false;
        if( isLooping ) {
            if( mDataList.size() == 1 ) {
                play();
            }else {
                //是否循环播放
                if( mPlayIndex >= mDataList.size() ) mPlayIndex = 0;
                if( ++mPlayIndex < mDataList.size() ) {
                    try { setSource( mDataList.get( mPlayIndex ) ); }
                    catch (IOException e) { e.printStackTrace(); }
                    play();
                }else {
                    release();
                }
            }
        }


        callCompletion( true );
    }

    private void callCompletion(boolean isForceComplete) {
        LogUtil.e("onCompletion -> " +
                "isForceComplete:" + isForceComplete + " | " +
                "curProgress:" + mCurrentProgress + " " +
                "maxProgress:" + ( mMediaPlayer == null ? -1 : mMediaPlayer.getDuration() )
        );
        if( mStatus == null ) return;
        mStatus.onCompletion(
                mPlayIndex,
                mDataList.size(),
                isForceComplete && mPlayIndex + 1 == mDataList.size()
        );
    }

    /**
     * 在线视频缓冲时进度
     * @param mp        播放器
     * @param percent   缓冲百分比
     */
    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        if( mStatus != null ) mStatus.onBufferingUpdate( percent );
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
//        mPrepared = 0;
//        setObjData( mCurrentData );
//        play();
        LogUtil.e("MediaX -> onError -> what:" + what + " | ext:" + extra);
        if( mStatus != null ) return mStatus.onError(what, extra);
        stop();
        initPrepared( -1 );
        return false;
    }
//    /**
//     * 视频尺寸发生改变。高度宽度为0时表示不可用，-1表示尚未初始化完成
//     * @param mp        {@link MediaPlayer}
//     * @param width     视频宽度
//     * @param height    视频高度
//     */
//    @Override
//    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
//        mVideoWidth = width;
//        mVideoHeight = height;
//        //视频尺寸尚未初始化时可能会调用updateOrientation()方法，所以获取视频尺寸后更新一次
//        updateOrientation( mScreenOrientationEventListener.getOrientationAngle() );
//        if( width <= 0 && height <= 0 && mStatus != null ) mStatus.onError( -1, -1 );
//    }
}